﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SQLServerDataAccess;
using System.Data;
using System.Web;
using Tools;
using System.Web.Routing;

namespace ViewDataBusiness
{
    public class DataBusiness
    {
        private string _UserID;
        private DataAccess _DataAccess; 
        private RouteValueDictionary _KeyList;

        public DataBusiness(string userID, RouteValueDictionary KeyList)
        {
            _UserID = userID;
            _KeyList = KeyList;
            _DataAccess = new DataAccess();
        }

        private Dictionary<string, object> SetParameters(List<QueryParameter> queryParameters, Dictionary<string, object> actionParameters)
        {
            Dictionary<string, object> commandParameters = null;
            string PName;

            if (actionParameters != null || queryParameters != null)
                commandParameters = new Dictionary<string, object>();

            if (actionParameters != null)
                foreach (string m in actionParameters.Keys)
                    if (m != "@KA" && m != "@KB" && m != "@KC" && m != "@KD")
                        commandParameters.Add(m, actionParameters[m]);

            if (queryParameters != null)
                foreach (QueryParameter m in queryParameters)
                {
                    PName = m.Name.Trim();
                    if (!commandParameters.ContainsKey(PName))
                        switch (m.ParameterType)
                        {
                            case ParameterType.Value:
                                switch (m.Value)
                                {
                                    case "#UserID":
                                        commandParameters.Add(PName, _UserID);
                                        break;
                                    case "#Username":
                                        commandParameters.Add(PName, SessionKey.GetUsername());
                                        break;
                                    case "#KeyA":
                                        commandParameters.Add(PName, _KeyList["KeyA"]);
                                        break;
                                    case "#KeyB":
                                        commandParameters.Add(PName, _KeyList["KeyB"]);
                                        break;
                                    case "#KeyC":
                                        commandParameters.Add(PName, _KeyList["KeyC"]);
                                        break;
                                    case "#KeyD":
                                        commandParameters.Add(PName, _KeyList["KeyD"]);
                                        break;
                                    default:
                                        commandParameters.Add(PName, m.Value);
                                        break;
                                }
                                break;
                            case ParameterType.PostGet:
                                commandParameters.Add(PName, HttpContext.Current.Request.Params[PName.Replace("@", "")] != null ? HttpContext.Current.Request.Params[PName.Replace("@", "")] : m.Value);
                                break;
                            case ParameterType.Post:
                                commandParameters.Add(PName, HttpContext.Current.Request.Form[PName.Replace("@", "")] != null ? HttpContext.Current.Request.Form[PName.Replace("@", "")] : m.Value);
                                break;
                            case ParameterType.Get:
                                commandParameters.Add(PName, HttpContext.Current.Request.QueryString[PName.Replace("@", "")] != null ? HttpContext.Current.Request.QueryString[PName.Replace("@", "")] : m.Value);
                                break;
                        }
                }

            return commandParameters;
        }

        private string OperationLink(List<string> OperationColum, DataRow dataRow)
        {
            if (OperationColum == null)
                return "";

            if (OperationColum[1].IndexOf("javascript:") == -1)
                switch (OperationColum.Count - 1)
                {
                    case 1:
                        return AsynchronousLogin.GetAsynchronousLoginUrl(String.Format(OperationColum[1]), HttpContext.Current.Request.QueryString["Permissions"]);
                    case 2:
                        return AsynchronousLogin.GetAsynchronousLoginUrl(String.Format(OperationColum[1], HttpContext.Current.Server.UrlEncode(dataRow[OperationColum[2]].ToString())), HttpContext.Current.Request.QueryString["Permissions"]);
                    case 3:
                        return AsynchronousLogin.GetAsynchronousLoginUrl(String.Format(OperationColum[1], HttpContext.Current.Server.UrlEncode(dataRow[OperationColum[2]].ToString()), HttpContext.Current.Server.UrlEncode(dataRow[OperationColum[3]].ToString())), HttpContext.Current.Request.QueryString["Permissions"]);
                    case 4:
                        return AsynchronousLogin.GetAsynchronousLoginUrl(String.Format(OperationColum[1], HttpContext.Current.Server.UrlEncode(dataRow[OperationColum[2]].ToString()), HttpContext.Current.Server.UrlEncode(dataRow[OperationColum[3]].ToString()), HttpContext.Current.Server.UrlEncode(dataRow[OperationColum[4]].ToString())), HttpContext.Current.Request.QueryString["Permissions"]);
                    case 5:
                        return AsynchronousLogin.GetAsynchronousLoginUrl(String.Format(OperationColum[1], HttpContext.Current.Server.UrlEncode(dataRow[OperationColum[2]].ToString()), HttpContext.Current.Server.UrlEncode(dataRow[OperationColum[3]].ToString()), HttpContext.Current.Server.UrlEncode(dataRow[OperationColum[4]].ToString()), HttpContext.Current.Server.UrlEncode(dataRow[OperationColum[5]].ToString())), HttpContext.Current.Request.QueryString["Permissions"]);
                }
            else
                switch (OperationColum.Count - 1)
                {
                    case 1:
                        return String.Format(OperationColum[1]);
                    case 2:
                        return String.Format(OperationColum[1], HttpContext.Current.Server.UrlEncode(dataRow[OperationColum[2]].ToString()));
                    case 3:
                        return String.Format(OperationColum[1], HttpContext.Current.Server.UrlEncode(dataRow[OperationColum[2]].ToString()), HttpContext.Current.Server.UrlEncode(dataRow[OperationColum[3]].ToString()));
                    case 4:
                        return String.Format(OperationColum[1], HttpContext.Current.Server.UrlEncode(dataRow[OperationColum[2]].ToString()), HttpContext.Current.Server.UrlEncode(dataRow[OperationColum[3]].ToString()), HttpContext.Current.Server.UrlEncode(dataRow[OperationColum[4]].ToString()));
                    case 5:
                        return String.Format(OperationColum[1], HttpContext.Current.Server.UrlEncode(dataRow[OperationColum[2]].ToString()), HttpContext.Current.Server.UrlEncode(dataRow[OperationColum[3]].ToString()), HttpContext.Current.Server.UrlEncode(dataRow[OperationColum[4]].ToString()), HttpContext.Current.Server.UrlEncode(dataRow[OperationColum[5]].ToString()));
                }

            return null;
        }

        public object FillData(Operation operation, Dictionary<string, object> actionParameters, string DataFormat, Dictionary<string, List<string>> OperationColums, int StartRecord, int MaxRecord)
        {
            try
            {
                CommandFill commandFill = new CommandFill()
                {
                    CommandText = operation.Query.QueryString,
                    CommandType = operation.Query.CommandType,
                    TableName = operation.Query.Tablename
                };

                if (StartRecord >= 0 && MaxRecord >= 0)
                {
                    commandFill.StartRecord = StartRecord;
                    commandFill.MaxRecord = MaxRecord;
                    operation.StartRecord = StartRecord;
                    operation.MaxRecord = MaxRecord;
                }

                commandFill.Parameters = SetParameters(operation.Query.Parameters, actionParameters);

                if (!String.IsNullOrEmpty(operation.Query.CountQuery))
                    operation.RecordCount = (int)_DataAccess.ExecuteScalar(new CommandExecute() { CommandText = operation.Query.CountQuery, CommandType = operation.Query.CommandType, Parameters = commandFill.Parameters });

                DataTable dataTable = _DataAccess.GetTable(commandFill);

                switch (DataFormat)
                {
                    case "FlexiGrid":
                        List<object> FlexiGridList = new List<object>();
                        Dictionary<string, List<object>> FlexiGridItem = null;
                        List<string> OperationLinks = new List<string>();
                        Dictionary<string, string> FieldLinks = new Dictionary<string, string>();
                        string IteraStr;
                        foreach (DataRow m in dataTable.Rows)
                        {
                            OperationLinks.Clear();
                            FieldLinks.Clear();
                            IteraStr = "";

                            if (OperationColums.Count > 0)
                                foreach (string p in OperationColums.Keys)
                                    if (OperationColums[p] != null)
                                        if (OperationColums[p][0] == null)
                                            if (OperationColums[p] != null)
                                                OperationLinks.Add("<a href=\"" + OperationLink(OperationColums[p], m) + "\" class=\"Operation\">" + p + "</a>");
                                            else
                                                OperationLinks.Add("<span class=\"NonOperation\">" + p + "</span>");
                                        else if (OperationColums[p] != null)
                                            FieldLinks.Add(OperationColums[p][0].ToLower(), "<a href=\"" + OperationLink(OperationColums[p], m) + "\" class=\"Operation\">?Field Name?</a>");

                            FlexiGridItem = new Dictionary<string, List<object>>() { { "cell", new List<object>() } };
                            foreach (DataColumn n in dataTable.Columns)
                                if (FieldLinks.ContainsKey(n.ColumnName.ToLower()))
                                    FlexiGridItem["cell"].Add(FieldLinks[n.ColumnName.ToLower()].Replace("?Field Name?", HttpContext.Current.Server.HtmlEncode(m[n.ColumnName].ToString())));
                                else
                                    FlexiGridItem["cell"].Add(HttpContext.Current.Server.HtmlEncode(m[n.ColumnName].ToString()));

                            foreach (string n in OperationLinks)
                                IteraStr += n;
                            FlexiGridItem["cell"].Add(IteraStr);

                            FlexiGridList.Add(FlexiGridItem);
                        }
                        return (object)(new Dictionary<string, object> { { "page", (StartRecord >= 0 && MaxRecord > 0) ? StartRecord / MaxRecord + 1 : 1 }, { "total", String.IsNullOrEmpty(operation.Query.CountQuery) ? 1 : operation.RecordCount }, { "rows", FlexiGridList }, { "MaxRecord", MaxRecord } });
                    case "SimpleList":
                        if (dataTable.Rows.Count > 0)
                        {
                            List<object> SimpleList = new List<object>();
                            List<object> SimpleListItem = null;
                            foreach (DataRow m in dataTable.Rows)
                            {
                                SimpleListItem = new List<object>();
                                foreach (DataColumn n in dataTable.Columns)
                                    SimpleListItem.Add(m[n.ColumnName]);

                                foreach (string p in OperationColums.Keys)
                                    SimpleListItem.Add(OperationLink(OperationColums[p], m));
                                SimpleList.Add(SimpleListItem);
                            }
                            return SimpleList;
                        }
                        break;
                    case "List":
                        if (dataTable.Rows.Count > 0)
                        {
                            List<string> List = new List<string>();
                            foreach (DataRow m in dataTable.Rows)
                                foreach (DataColumn n in dataTable.Columns)
                                    List.Add(m[n.ColumnName].ToString());
                            return List;
                        }
                        break;
                    default:
                        if (dataTable.Rows.Count > 0)
                        {
                            List<object> ReturnData = new List<object>();
                            Dictionary<string, object> DataItem = null;
                            foreach (DataRow m in dataTable.Rows)
                            {
                                DataItem = new Dictionary<string, object>();
                                foreach (DataColumn n in dataTable.Columns)
                                    DataItem.Add(n.ColumnName, m[n.ColumnName]);

                                foreach (string p in OperationColums.Keys)
                                    DataItem.Add(p, OperationLink(OperationColums[p], m));
                                ReturnData.Add(DataItem);
                            }
                            return ReturnData;
                        }
                        break;
                }
                return null;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public int ExecuteNonQuery(Operation operation, Dictionary<string, object> actionParameters)
        {
            try
            {
                CommandExecute commandExecute = new CommandExecute()
                {
                    CommandText = operation.Query.QueryString,
                    CommandType = operation.Query.CommandType
                };

                commandExecute.Parameters = SetParameters(operation.Query.Parameters, actionParameters);

                return _DataAccess.TransactionExecute(commandExecute);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public int ExecuteNonQuery(List<Operation> operations, List<Dictionary<string, object>> actionParameters)
        {
            try
            {
                CommandExecute commandExecute;
                List<CommandExecute> commandExecutes = new List<CommandExecute>();

                for (int i = 0; i < operations.Count(); i++)
                {
                    commandExecute = new CommandExecute()
                    {
                        CommandText = operations[i].Query.QueryString,
                        CommandType = operations[i].Query.CommandType
                    };

                    commandExecute.Parameters = SetParameters(operations[i].Query.Parameters, actionParameters[i]);
                    commandExecutes.Add(commandExecute);
                }
                return _DataAccess.TransactionExecute(commandExecutes);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public object ExecuteScalar(Operation operation, Dictionary<string, object> actionParameters)
        {
            try
            {
                CommandExecute commandExecute = new CommandExecute()
                {
                    CommandText = operation.Query.QueryString,
                    CommandType = operation.Query.CommandType
                };

                commandExecute.Parameters = SetParameters(operation.Query.Parameters, actionParameters);
                return _DataAccess.ExecuteScalar(commandExecute);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        } 
    }
}
